﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Pahan.McuFusion.Common;
using Pahan.McuFusion.Common.Utils;

namespace Pahan.McuFusion.UI.Workspaces
{
    [Serializable]
    public partial class Workspace : ISerializable
    {
        private Workspace(SerializationInfo info, StreamingContext context)
        {
            this.programmer = info.GetValue<IProgrammer>(programmerKey);
            this.ProgrammerInfo = programmer.Info;
            this.adapter = info.GetValue<IHardwareAdapter>(adapterKey);
            this.hwInterface = info.GetValue<IHardwareInterface>(interfaceKey);
            this.DeviceInfo = info.GetValue<DeviceInfo>(deviceInfoKey);
            this.HardwareAdapterInfo = info.GetValue<HardwareAdapterInfo>(adapterInfoKey);
            this.HardwareInterfaceInfo = info.GetValue<HardwareInterfaceInfo>(interfaceInfoKey);
        }

        #region Implementation of ISerializable

        /// <summary>
        /// Populates a <see cref="TValue:System.Runtime.Serialization.SerializationInfo"></see> with the data needed to serialize the target object.
        /// </summary>
        /// <param name="context">The destination (see <see cref="TValue:System.Runtime.Serialization.StreamingContext"></see>) for this serialization. </param>
        /// <param name="info">The <see cref="TValue:System.Runtime.Serialization.SerializationInfo"></see> to populate with data. </param>
        /// <exception cref="TValue:System.Security.SecurityException">The caller does not have the required permission. </exception>
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(versionKey, currentVersion);
            info.AddValue(programmerKey, programmer);
            info.AddValue(adapterKey, adapter);
            info.AddValue(interfaceKey, hwInterface);
            info.AddValue(deviceInfoKey, DeviceInfo);
            info.AddValue(adapterInfoKey, HardwareAdapterInfo);
            info.AddValue(interfaceInfoKey, HardwareInterfaceInfo);
        }

        #endregion

        #region Constants

        private static readonly Version currentVersion = new Version(1, 0);

        private const String versionKey = "Version";
        private const String programmerKey = "Programmer";
        private const String adapterKey = "Adapter";
        private const String interfaceKey = "Interface";
        private const String deviceInfoKey = "DeviceInfo";
        private const String adapterInfoKey = "AdapterInfo";
        private const String interfaceInfoKey = "InterfaceInfo";

        #endregion

        #region Save/Load

        public void Save(FileInfo file)
        {
            using (FileStream stream = file.OpenWrite())
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(stream, this);
                path = file.FullName;
                Name = System.IO.Path.GetFileNameWithoutExtension(file.Name);
                Modified = false;
            }
        }

        public static Workspace Load(FileInfo file)
        {
            using (FileStream stream = file.OpenRead())
            {
                using (AssemblyLoader.GetAssemblyResolutionScope())
                {
                    var formatter = new BinaryFormatter();
                    formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
                    var workspace = (Workspace)formatter.Deserialize(stream);
                    workspace.path = file.FullName;
                    workspace.Name = System.IO.Path.GetFileNameWithoutExtension(file.Name);
                    workspace.Modified = false;
                    return workspace;
                }
            }
        }

        #endregion
    }
}
